package com.google.springfacestools.config;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindException;
import org.springframework.validation.Validator;

import com.google.springfacestools.Out;
import com.google.springfacestools.validation.Validate;
import com.google.springfacestools.validation.ValidationMessages;

@Component
@Aspect
public class ValidateInterceptor {

	@Autowired
	private BeanFactory beanFactory;
	
	@Autowired
	@Out(value="validationErrors", scope="request")
	private ValidationMessages validationErrors;
	
	@Around("@annotation(validate)")
	protected Object execute(ProceedingJoinPoint pjp, Validate validate) throws Throwable {
		Object bean = beanFactory.getBean(validate.bean());
		Validator validator;
		if(StringUtils.hasText(validate.validator())) {
			validator = (Validator) beanFactory.getBean(validate.validator());	
		} else {
			validator = (Validator) beanFactory.getBean(validate.bean() + "Validator");
		}
		
		if(validator.supports(AopUtils.getTargetClass(bean))) {
			BindException bind = new BindException(bean, validate.bean());
			validator.validate(bean, bind);
			
			if(bind.hasErrors()) {
				validationErrors.addErrors(validate.bean(), bind);
				return null;
			}
		}
		return pjp.proceed();
	}
	
}
